<template>
  <span class="fm-style">
    <el-container class="fm2-container">
      <el-main class="fm2-main">
        <el-container>
          <el-aside width="250px">
            <div class="components-list">
              <template v-if="basicFields.length">
                <div class="widget-cate">基础字段</div>
                <draggable
                  tag="ul"
                  :list="basicComponents"
                  v-bind="{
                    group: { name: 'people', pull: 'clone', put: false },
                    sort: false,
                    ghostClass: 'ghost',
                  }"
                  :move="handleMove"
                  @end="handleMoveEnd"
                  @start="handleMoveStart"
                >
                  <template v-for="(item, index) in basicComponents">
                    <li
                      v-if="basicFields.indexOf(item.type) >= 0"
                      :key="index"
                      class="form-edit-widget-label"
                      :class="{ 'no-put': item.type == 'divider' }"
                    >
                      <a>
                        <i class="icon iconfont" :class="item.icon" />
                        <span>{{ item.name }}</span>
                      </a>
                    </li>
                  </template>
                </draggable>
              </template>

              <template v-if="advanceFields.length">
                <div class="widget-cate">业务字段</div>
                <draggable
                  tag="ul"
                  :list="advanceComponents"
                  v-bind="{
                    group: { name: 'people', pull: 'clone', put: false },
                    sort: false,
                    ghostClass: 'ghost',
                  }"
                  :move="handleMove"
                  @end="handleMoveEnd"
                  @start="handleMoveStart"
                >
                  <template v-for="(item, index) in advanceComponents">
                    <li
                      v-if="advanceFields.indexOf(item.type) >= 0"
                      :key="index"
                      class="form-edit-widget-label"
                      :class="{ 'no-put': item.type == 'table' }"
                    >
                      <a>
                        <i class="icon iconfont" :class="item.icon" />
                        <span>{{ item.name }}</span>
                      </a>
                    </li>
                  </template>
                </draggable>
              </template>
            </div>
          </el-aside>
          <el-container class="center-container" direction="vertical">
            <el-header v-if="isDev" class="btn-bar" style="height: 45px">
              <slot name="action" />
              <el-button
                type="text"
                size="medium"
                icon="el-icon-download"
                @click="saveFormJson"
                >{{ $t("fm.actions.saveFormJson") }}</el-button
              >
              <el-button
                v-if="upload"
                type="text"
                size="medium"
                icon="el-icon-upload2"
                @click="handleUpload"
                >{{ $t("fm.actions.import") }}</el-button
              >
              <el-button
                v-if="clearable"
                type="text"
                size="medium"
                icon="el-icon-delete"
                @click="handleClear"
                >{{ $t("fm.actions.clear") }}</el-button
              >
              <el-button
                v-if="preview"
                type="text"
                size="medium"
                icon="el-icon-view"
                @click="handlePreview"
                >{{ $t("fm.actions.preview") }}</el-button
              >
              <el-button
                v-if="generateJson"
                type="text"
                size="medium"
                icon="el-icon-tickets"
                @click="handleGenerateJson"
                >{{ $t("fm.actions.json") }}</el-button
              >
              <el-button
                v-if="generateCode"
                type="text"
                size="medium"
                icon="el-icon-document"
                @click="handleGenerateCode"
                >{{ $t("fm.actions.code") }}</el-button
              >
            </el-header>
            <el-main :class="{ 'widget-empty': widgetForm.list.length == 0 }">
              <widget-form
                v-if="!resetJson"
                ref="widgetForm"
                :data="widgetForm"
                :select.sync="widgetFormSelect"
              />
            </el-main>
          </el-container>

          <el-aside class="widget-config-container">
            <el-container>
              <el-header height="45px">
                <div
                  class="config-tab"
                  :class="{ active: configTab == 'widget' }"
                  @click="handleConfigSelect('widget')"
                >
                  {{ $t("fm.config.widget.title") }}
                </div>
                <div
                  class="config-tab"
                  :class="{ active: configTab == 'form' }"
                  @click="handleConfigSelect('form')"
                >
                  {{ $t("fm.config.form.title") }}
                </div>
              </el-header>
              <el-main class="config-content">
                <widget-config
                  v-show="configTab == 'widget'"
                  :data="widgetFormSelect"
                />
                <form-config
                  v-show="configTab == 'form'"
                  :data="widgetForm.config"
                />
              </el-main>
            </el-container>
          </el-aside>

          <cus-dialog
            ref="widgetPreview"
            :visible="previewVisible"
            width="1000px"
            form
            @on-close="previewVisible = false"
          >
            <generate-form
              v-if="previewVisible"
              ref="generateForm"
              insite="true"
              :checkedShow="[]"
              :checkedEdit="[]"
              :isPre="true"
              :data="widgetForm"
              :value="widgetModels"
              :remote="remoteFuncs"
              @on-change="handleDataChange"
            >
              <template v-slot:blank="scope">
                Width
                <el-input
                  v-model="scope.model.blank.width"
                  style="width: 100px"
                />
                Height
                <el-input
                  v-model="scope.model.blank.height"
                  style="width: 100px"
                />
              </template>
            </generate-form>

            <template slot="action">
              <el-button type="primary" @click="handleTest">{{
                $t("fm.actions.getData")
              }}</el-button>
              <el-button @click="handleReset">{{
                $t("fm.actions.reset")
              }}</el-button>
            </template>
          </cus-dialog>

          <cus-dialog
            ref="uploadJson"
            :visible="uploadVisible"
            width="800px"
            form
            @on-close="uploadVisible = false"
            @on-submit="handleUploadJson"
          >
            <el-alert
              type="info"
              :title="$t('fm.description.uploadJsonInfo')"
            />
            <div id="uploadeditor" style="height: 400px; width: 100%">
              {{ jsonEg }}
            </div>
          </cus-dialog>

          <cus-dialog
            ref="jsonPreview"
            :visible="jsonVisible"
            width="800px"
            form
            @on-close="jsonVisible = false"
          >
            <editor
              height="500"
              width="100%"
              ref="editor"
              :content="jsonTemplate"
              v-model="jsonTemplate"
              :lang="'json'"
              @init="initEditor"
            />
            <template slot="action">
              <el-button
                type="primary"
                size="mini"
                class="json-btn"
                :data-clipboard-text="jsonCopyValue"
                >{{ $t("fm.actions.copyData") }}</el-button
              >
            </template>
          </cus-dialog>

          <cus-dialog
            ref="codePreview"
            :visible="codeVisible"
            width="800px"
            form
            :action="false"
            @on-close="codeVisible = false"
          >
            <!-- <div id="codeeditor" style="height: 500px; width: 100%;">{{indexTemplate}}</div> -->
            <el-tabs
              v-model="codeActiveName"
              type="border-card"
              style="box-shadow: none"
            >
              <el-tab-pane label="详情页代码" name="vue">
                <editor
                  height="500"
                  width="100%"
                  ref="editor"
                  :content="detailTemplate"
                  v-model="detailTemplate"
                  :lang="'html'"
                  @init="initEditor"
                />
              </el-tab-pane>
              <el-tab-pane label="列表页代码" name="html">
                <editor
                  height="500"
                  width="100%"
                  ref="editor"
                  :content="indexTemplate"
                  v-model="indexTemplate"
                  :lang="'html'"
                  @init="initEditor"
                />
              </el-tab-pane>
            </el-tabs>
          </cus-dialog>
        </el-container>
      </el-main>
    </el-container>
  </span>
</template>

<script>
import Draggable from "vuedraggable";
import WidgetConfig from "./WidgetConfig";
import FormConfig from "./FormConfig";
import WidgetForm from "./WidgetForm";
import CusDialog from "./CusDialog";
import GenerateForm from "./GenerateForm";
import Clipboard from "clipboard";
import { basicComponents, advanceComponents } from "./componentsConfig.js";
import generateCode from "./generateCode.js";
import generateModel from "./generateModel";
import Editor from "vue2-ace-editor";
import { updateFormJson } from "@/api/system/moduleform";
import { createVue } from "@/api/system/codegen";

export default {
  name: "vueForm",
  components: {
    Draggable,
    WidgetConfig,
    FormConfig,
    WidgetForm,
    CusDialog,
    GenerateForm,
    Editor,
  },
  props: {
    formJson: {
      type: Object,
    },
    moduleFormId: {
      type: String,
    },
    preview: {
      type: Boolean,
      default: false,
    },
    generateCode: {
      type: Boolean,
      default: false,
    },
    generateJson: {
      type: Boolean,
      default: false,
    },
    upload: {
      type: Boolean,
      default: false,
    },
    clearable: {
      type: Boolean,
      default: false,
    },
    basicFields: {
      type: Array,
      default: () => [
        "input",
        "textarea",
        "number",
        "radio",
        "checkbox",
        "time",
        "date",
        "rate",
        "color",
        "select",
        "switch",
        "slider",
        "text",
        "blank",
        "imgupload",
        "editor",
        "cascader",
        "grid",
      ],
    },
    advanceFields: {
      type: Array,
      default: () => ["role", "organize", "user", "dictionary", "menu"],
    },
    isDev: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      basicComponents,
      advanceComponents,
      resetJson: false,
      widgetForm: {
        list: [],
        config: {
          labelWidth: 100,
          labelPosition: "right",
          size: "small",
        },
      },
      configTab: "widget",
      widgetFormSelect: null,
      previewVisible: false,
      jsonVisible: false,
      codeVisible: false,
      uploadVisible: false,
      remoteFuncs: {
        func_test(resolve) {
          setTimeout(() => {
            const options = [
              { id: "1", name: "1111" },
              { id: "2", name: "2222" },
              { id: "3", name: "3333" },
            ];

            resolve(options);
          }, 2000);
        },
        upload_callback(response, file, fileList) {
          console.log("callback", response, file, fileList);
        },
      },
      widgetModels: {},
      blank: "",
      indexTemplate: "",
      detailTemplate: "",
      jsonTemplate: "",
      uploadEditor: null,
      jsonCopyValue: "",
      jsonClipboard: null,
      jsonEg: `{
        "list": [],
        "config": {
          "labelWidth": 100,
          "labelPosition": "top",
          "size": "small"
        }
      }`,
      codeActiveName: "vue",
    };
  },
  watch: {
    widgetForm: {
      deep: true,
      handler: function (val) {},
    },
    $lang: function (val) {
      this._loadComponents();
    },
  },
  created() {
    this.setJSON(this.formJson);
  },
  mounted() {
    this._loadComponents();
  },
  methods: {


    initEditor: function (editor) {
      require("brace/mode/html");
      require("brace/mode/javascript");
      require("brace/theme/chrome");
    },
    _loadComponents() {
      this.basicComponents = this.basicComponents.map((item) => {
        return {
          ...item,
          name: this.$t(`fm.components.fields.${item.type}`),
        };
      });
      this.advanceComponents = this.advanceComponents.map((item) => {
        return {
          ...item,
          name: this.$t(`fm.components.fields.${item.type}`),
        };
      });
    },
    handleConfigSelect(value) {
      this.configTab = value;
    },
    handleMoveEnd(evt) {
      console.log("end", evt);
    },
    handleMoveStart({ oldIndex }) {
      console.log("start", oldIndex, this.basicComponents);
    },
    handleMove() {
      return true;
    },
    handlePreview() {
      this.previewVisible = true;
    },
    handleTest() {
      this.$refs.generateForm
        .getData()
        .then((data) => {
          this.$alert(data, "").catch((e) => {});
          this.$refs.widgetPreview.end();
        })
        .catch((e) => {
          this.$refs.widgetPreview.end();
        });
    },
    handleReset() {
      this.$refs.generateForm.reset();
    },
    saveFormJson() {
      let json = JSON.stringify(this.widgetForm);
      let params = {
        formJson: json,
        id: this.moduleFormId,
      };
      updateFormJson(params)
        .then((response) => {
          this.$notify({
            title: "保存成功",
            type: "success",
            duration: 1500,
          });
        })
        .catch((response) => {
          this.$notify({
            title: "保存失败",
            type: "error",
            duration: 2500,
          });
        });
    },
    //这个方法在页面载入的时候 tab切换的时候 触发   在关闭 保存的时候清空
    returnTempJson() {
      let json = JSON.stringify(this.widgetForm);
      return json;
    },
    handleGenerateJson() {
      this.jsonVisible = true;
      this.jsonTemplate = JSON.stringify(this.widgetForm, null, 2);
      this.$nextTick(() => {
        if (!this.jsonClipboard) {
          this.jsonClipboard = new Clipboard(".json-btn");
          this.jsonClipboard.on("success", (e) => {
            this.$message.success(this.$t("fm.message.copySuccess"));
          });
        }
        this.jsonCopyValue = JSON.stringify(this.widgetForm);
      });
    },
    handleGenerateCode() {
      this.codeVisible = true;
      const { models, rules } = generateModel(this.widgetForm.list);
      createVue({
        data: this.widgetForm,
        models: models,
        rules: rules,
      }).then((res) => {
        this.detailTemplate = res.data;
      });

      this.indexTemplate = generateCode(
        JSON.stringify(this.widgetForm),
        "html"
      );
    },
    handleUpload() {
      this.uploadVisible = true;
    },
    handleUploadJson() {
      try {
        // this.setJSON(JSON.parse( ))
        this.uploadVisible = false;
      } catch (e) {
        this.$message.error(e.message);
        this.$refs.uploadJson.end();
      }
    },
    handleClear() {
      this.widgetForm = {
        list: [],
        config: {
          labelWidth: 100,
          labelPosition: "right",
          size: "small",
          customClass: "",
        },
      };

      this.widgetFormSelect = {};
    },
    clear() {
      this.handleClear();
    },
    getJSON() {
      return this.widgetForm;
    },
    setJSON(json) {
      if (json && json.list.length > 0) {
        this.widgetForm = json;
        this.widgetFormSelect = json.list[0];
      }
    },
    handleInput(val) {
      this.blank = val;
    },
    handleDataChange(field, value, data) {
      console.log(field, value, data);
    },
  },
};
</script>
